package com.st.api.util;

import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import com.novell.ldap.LDAPAttribute;
import com.novell.ldap.LDAPAttributeSet;
import com.novell.ldap.LDAPConnection;
import com.novell.ldap.LDAPEntry;
import com.novell.ldap.LDAPException;
import com.novell.ldap.LDAPSearchResults;

public class LdapUserAuth{
	
	
	static String   ldapHost = "10.135.7.142";
	static String loginDN = "cn=jhbuser,ou=user,o=services";
	static String loginPassword = "jhbuser@20150928";
    /**
     * 获得ldap链接
     * @return
     */
    private static synchronized LDAPConnection  getLDAPConnection(String ldapHost,String loginDN,String password){
    	LDAPConnection lc = null;
    	try {
	    	int ldapVersion = LDAPConnection.LDAP_V3;
	        int ldapPort = 389;
	        lc = new LDAPConnection();
			lc.connect( ldapHost, ldapPort );
			lc.bind( ldapVersion, loginDN, password );
			return lc;
		} catch (LDAPException e) {
			e.printStackTrace();
			if(lc != null){
				try {
					lc.disconnect();
					lc = null;
				} catch (LDAPException e1) {
					e1.printStackTrace();
				}
			}
			return null;
		}
    }
    /**
     * 释放ldap链接
     * @param lc
     */
    private static void releaseLDAPConnection(LDAPConnection lc){
    	try {
    		if(lc != null){
    			lc.disconnect();
    			lc = null;
    		}
		} catch (LDAPException e) {
			e.printStackTrace();
		}
    }
    /**
     * 获得dn
     * @param lc
     * @param cn : 工号cn
     * @return
     */
    private static synchronized String getDN(LDAPConnection lc,String cn){
    	 try { 
    		 if((cn == null || "".equals(cn))){
	   			 return null;
	   		 }
    		 //haier 下面只查cn
             String searchBase = "o=haier"; 
             String searchFilter = "(&(cn="+cn+")(objectClass=user))";
             int searchScope = LDAPConnection.SCOPE_SUB; 
             LDAPSearchResults searchResults = lc.search(searchBase,searchScope, searchFilter.toString(), null, false); 
             while (searchResults.hasMore()) {
                 LDAPEntry nextEntry = null; 
                 nextEntry = searchResults.next(); 
                 String str = nextEntry.getDN(); 
                 return str;
             }
             return null;
         } catch (LDAPException t) { 
         	t.printStackTrace();
         	return null;
         }
    }
    /**
     * 校验用户是否合法
     */
    public  String checkInfo(String ldapHost,String loginDN,String loginPassword,String dn,String pwd){
    	int ldapVersion   = LDAPConnection.LDAP_V3;
        int ldapPort      = 389;
        
        LDAPConnection lc = new LDAPConnection();
        try {
            lc.connect( ldapHost, ldapPort );
            lc.bind( ldapVersion, loginDN, loginPassword.getBytes("UTF8") );
            Map<String,String> map  = getOperationalAttrs( lc, dn );
            //开始判断
			String logindisabled = map.get("logindisabled");
			if(logindisabled.equalsIgnoreCase("TRUE")){
			//	System.out.println("用户已被锁定！");
				return "用户已被锁定！";
			}
			String loginIntruderAttempts = map.get("loginIntruderAttempts");
			if(loginIntruderAttempts!=null && !"".equals(loginIntruderAttempts)){
				int loginIntruderAttemptsInt = Integer.parseInt(loginIntruderAttempts);
				if(loginIntruderAttemptsInt>=5){
				//	System.out.println("账号锁定，输入错误密码次数"+loginIntruderAttemptsInt+"次！");
					return "账号锁定，输入错误密码次数"+loginIntruderAttemptsInt+"次！";
				}
			}
			//超期
			SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssZ");
			String now = sdf.format(new Date());
			String loginExpirationTime = map.get("loginExpirationTime");
			if(loginExpirationTime!=null && !"".equals(loginExpirationTime)){
				if(now.compareTo(loginExpirationTime)>0){
				//	System.out.println("用户密码已经过期！");
					return "用户密码已经过期！";
				}
			}
			//强制修改密码
			String passwordExpirationTime = map.get("passwordExpirationTime");
			if(passwordExpirationTime!=null && !"".equals(passwordExpirationTime)){
				if(now.compareTo(passwordExpirationTime)>0){
				//	System.out.println("2个月内未修改密码，请修改后再登录");
					return "2个月内未修改密码，请修改后再登录";
				}
			}
			//判断密码
			LDAPAttribute pwdAttr = new LDAPAttribute("userPassword", pwd );
			boolean pwdCorrect = lc.compare( dn, pwdAttr );
		//	System.out.println( pwdCorrect ? "密码正确":"密码错误.\n");
            lc.disconnect();
            return pwdCorrect ? "密码正确":"密码错误.\n";
        }catch( LDAPException e ) {
            System.out.println( "\nError: " + e.toString() );
            e.printStackTrace();
            System.exit(1);
        }catch( UnsupportedEncodingException e ) {
            System.out.println( "Error: " + e.toString() );
            e.printStackTrace();
        }
        return "验证过程错误，联系系统运维人员！";
     //   System.exit(0);
    }
    /**
     * 获取用户属性信息
     * @param lc
     * @param dn
     * @throws LDAPException
     */
    public Map<String,String>  getOperationalAttrs( LDAPConnection lc, String dn)throws LDAPException{
    	String returnAttrs[] = {"HaierUserDeptName","mail","mobile","fullName","HaierUserOU","logindisabled","loginExpirationTime","loginIntruderAttempts","passwordExpirationTime"};
    	Map<String,String> map = new HashMap<String,String>();
        String attributeName, attrValue;
        Iterator allAttributes;
        Enumeration allValues;
        LDAPAttribute attribute;
        LDAPAttributeSet attributeSet;
        for(String str:returnAttrs){
        	map.put(str, "");
        }
        try {
            LDAPEntry entry = lc.read(dn, returnAttrs);   //
            
            attributeSet = entry.getAttributeSet();
            allAttributes = attributeSet.iterator();
            while(allAttributes.hasNext()) {
                attribute = (LDAPAttribute)allAttributes.next();
                attributeName = attribute.getName();
             //   System.out.println("----------"+attributeName);
                if ( (allValues = attribute.getStringValues()) != null
                  && (attrValue = (String) allValues.nextElement()) != null) {
                	map.put(attributeName, attrValue);
                }
            }
            return map;
        }catch( LDAPException e ) {
            System.err.println( "\nOperationalAttrs() failed.");
            System.err.println( "\nError: " + e.toString() );
            System.exit(1);
            return map;
        }
    }
    
    //validate user 
    public static String validateUserLogin(String userid,String password){
    	LdapUserAuth info = new LdapUserAuth();
  
        //获取链接
        LDAPConnection connection = getLDAPConnection(ldapHost,loginDN,loginPassword);
        //获取用户dn
        String dn = info.getDN(connection, userid);
        String loginInfo = null;
        try {
        	loginInfo = info.checkInfo( ldapHost, loginDN, loginPassword, dn, password);
		} catch (Exception e) {
			//用户名不存在情况下
			loginInfo = "用户名/密码错误";
		}
      
        //释放链接
    	releaseLDAPConnection(connection);
        
    	return loginInfo;
    	
    }
    
    
    public static Map<String,String> getUserInfoMap(String userid) throws LDAPException{
    	
    	LdapUserAuth info = new LdapUserAuth();  	
        
        //获取链接
        LDAPConnection connection = getLDAPConnection(ldapHost,loginDN,loginPassword);
        //获取用户dn
        String dn = info.getDN(connection, userid);
        
        Map<String,String> userinfoMap=info.getOperationalAttrs(connection,dn);
        
    	//释放链接
    	releaseLDAPConnection(connection);
        
        return userinfoMap;
    }
    public static void main( String[] args ){
    	LdapUserAuth info = new LdapUserAuth();
    	//下面信息需要自己填写
        String cn = "01345496";
        String pwd = "Hr12345678";
        //获取链接
        LDAPConnection connection = getLDAPConnection(ldapHost,loginDN,loginPassword);
        //获取用户dn
        String dn = info.getDN(connection, cn);
        //用户认证
    	System.out.println(info.checkInfo( ldapHost, loginDN, loginPassword, dn, pwd));
    	
    	//获取用户信息
    	try {
			Map<String,String> userinfoMap=info.getOperationalAttrs(connection,dn);
			
			for (Map.Entry<String, String> m :userinfoMap.entrySet())  {  
	            System.out.println(m.getKey()+"\t"+m.getValue());  
	        }  

		} catch (LDAPException e) {
			e.printStackTrace();
		}
    	//释放链接
    	releaseLDAPConnection(connection);
    }
}
